using System;
using System.Activities;
using System.Activities.Statements;
using Headsight.BPMN2WF.Transformation;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Headsight.BPMN2WF.WF.Simplification
{
    [TestClass]
    public class WFSimplifier_IfThenSequenceTest : WFSimplifier_TestFixture<WFSimplifierIfThenSequence>
    {
        private Object _flowIn;
        private Object _flowOut;

        protected override WFSimplifierIfThenSequence CreateSut()
        {
            _flowIn = new Object();
            _flowOut = new Object();

            return new WFSimplifierIfThenSequence();
        }

        private BPMNTransformationResult CreateBPMNTransformationResult(Activity activity)
        {
            return new BPMNTransformationResult(activity, _flowIn, _flowOut);
        }

        private void Verify_BPMNTransformationResult(Activity activity, BPMNTransformationResult actual)
        {
            // This kind of simplication shall not alter the overall / original's BPMNTransformation result;
            // the respective operation operates on 'lower' (non-block) level and therefore does not
            // change an block's overall result.
            Assert.AreSame(activity, actual.Result);
            Assert.AreSame(_flowIn, actual.FlowIn);
            Assert.AreSame(_flowOut, actual.FlowOut);
        }

        [TestMethod]
        public void Probe_always_returns_true()
        {
            Assert.AreEqual(true, _sut.Probe(_ctx, CreateBPMNTransformationResult(new If())));
            Assert.AreEqual(true, _sut.Probe(_ctx, CreateBPMNTransformationResult(new Flowchart())));
            Assert.AreEqual(true, _sut.Probe(_ctx, CreateBPMNTransformationResult(new Sequence())));
            Assert.AreEqual(true, _sut.Probe(_ctx, CreateBPMNTransformationResult(null)));
        }

        [TestMethod]
        public void Simplify_inco_empty_Sequence()
        {
            var activity = new Sequence();
            var actual = _sut.Simplify(_ctx, CreateBPMNTransformationResult(activity));

            Verify_BPMNTransformationResult(activity, actual);
        }

        [TestMethod]
        public void Simplify_inco_empty_Flowchart()
        {
            var activity = new Flowchart();
            var actual = _sut.Simplify(_ctx, CreateBPMNTransformationResult(activity));

            Verify_BPMNTransformationResult(activity, actual);
        }

        [TestMethod]
        public void Simplify_inco_Sequence_of_IfThen_Sequence_of_Sequences()
        {
            var sequence = CreateSequence(_activity1, new If
            {
                Then =
                    CreateSequence(_activity1,
                                    CreateSequence(_activity2, _activity3))
            }, _activity3);

            var actual = _sut.Simplify(_ctx, CreateBPMNTransformationResult(sequence));

            Verify_BPMNTransformationResult(sequence, actual);

            var actualSequence = (Sequence) actual.Result;

            var actualIf = (If) actualSequence.Activities[1];
            var actualIfSeq = (Sequence)actualIf.Then;

            Assert.AreEqual(3, actualIfSeq.Activities.Count);
            Assert.AreSame(_activity1, actualIfSeq.Activities[0]);
            Assert.AreSame(_activity2, actualIfSeq.Activities[1]);
            Assert.AreSame(_activity3, actualIfSeq.Activities[2]);
        }

        [TestMethod]
        public void Simplify_inco_Flowchart_of_IfThen_Sequence_of_Sequences()
        {
            var flowchart = new Flowchart();
            flowchart.Nodes.Add(new FlowStep { Action = _activity1 });
            flowchart.Nodes.Add(new FlowStep { Action = _activity2 }); 
            flowchart.Nodes.Add(new FlowStep { Action = _activity3 });

            var ifActivity = new If
            {
                Then = CreateSequence(_activity1, CreateSequence(_activity2, _activity3))
            };
            flowchart.Nodes.Add(new FlowStep { Action = ifActivity });

            var actual = _sut.Simplify(_ctx, CreateBPMNTransformationResult(flowchart));

            Verify_BPMNTransformationResult(flowchart, actual);

            var actualFlowchart = (Flowchart)actual.Result;

            Assert.AreEqual(4, actualFlowchart.Nodes.Count);
            Assert.AreSame(_activity1, ((FlowStep)actualFlowchart.Nodes[0]).Action);
            Assert.AreSame(_activity2, ((FlowStep)actualFlowchart.Nodes[1]).Action);
            Assert.AreSame(_activity3, ((FlowStep)actualFlowchart.Nodes[2]).Action);
            Assert.AreSame(ifActivity, ((FlowStep)actualFlowchart.Nodes[3]).Action);

            var actualIf = (If) ((FlowStep) actualFlowchart.Nodes[3]).Action;
            var actualIfSeq = (Sequence)actualIf.Then;

            Assert.AreEqual(3, actualIfSeq.Activities.Count);
            Assert.AreSame(_activity1, actualIfSeq.Activities[0]);
            Assert.AreSame(_activity2, actualIfSeq.Activities[1]);
            Assert.AreSame(_activity3, actualIfSeq.Activities[2]);
        }
    }
}
